package com.glasses.manage.export.excel;

import com.glasses.manage.export.DataExportor;
import com.glasses.manage.export.DataField;
import com.glasses.manage.export.DataPage;
import com.glasses.manage.export.ExportDataSource;
import com.glasses.manage.export.csv.CsvDataExportor;
import jxl.Workbook;
import jxl.format.UnderlineStyle;
import jxl.write.*;
import jxl.write.Number;
import jxl.write.biff.RowsExceededException;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;


/**
 * 描述: Excel数据导出工具,默认为CSV格式,CSV格式文件可以用excel正常打开(兼容03和07+) 如果指定为Excel,则导出Excel03
 *
 * @author yy
 */
public class ExcelDataExportor<T> extends DataExportor<T> {
    private MODE mode;

    private String sheetName;


    public ExcelDataExportor(List<DataField> fields, ExportDataSource<T> dataSource, OutputStream os) {
        this(fields, dataSource, os, MODE.CSV);
    }

    /**
     * 没有分页参数调用
     *
     * @param fields
     * @param dataSource
     * @param os
     * @param mode
     */
    public ExcelDataExportor(List<DataField> fields, ExportDataSource<T> dataSource, OutputStream os, MODE mode) {
        super(null, fields, dataSource, os);
        this.mode = mode;
    }

    /**
     * 带分页参数
     *
     * @param pageParam
     * @param fields
     * @param dataSource
     * @param os
     * @param mode
     */
    public ExcelDataExportor(DataPage pageParam, List<DataField> fields, ExportDataSource<T> dataSource, OutputStream os, MODE mode) {
        super(pageParam, fields, dataSource, os);
        this.mode = mode;
    }

    @Override
    public void export() throws IOException {
        if (mode == null || mode == MODE.CSV) {
            new CsvDataExportor<T>(fields, dataSource, os).export();
        } else {
            try {
                if (pageParam == null) {
                    exportExcel07();
                } else {
                    exportExcel07ForPage();
                }
            } catch (RowsExceededException e) {
                throw new RuntimeException(e);
            } catch (WriteException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void exportExcel07ForPage() throws IOException, WriteException {
        Collection<?> dataList;
        WritableWorkbook workBook = Workbook.createWorkbook(os);
        dataList = dataSource.getData();
        int countPage = 1;
        //如果下载的数据存在且需要分页
        if (dataList.size() > 0) {
            countPage = (dataList.size() % pageParam.getMaxEntityInOnePage()) == 0 ? (dataList.size() / pageParam.getMaxEntityInOnePage()) : (dataList.size() / pageParam.getMaxEntityInOnePage()) + 1;
        }

        int maxEntityInOnePage = pageParam.getMaxEntityInOnePage();// 一页中最多条目数
        int sheetIndex = 1;
        int rowIndex = 1;
        int roeIndexPage = 1;
        WritableSheet sheet = workBook.createSheet(createSheetName(sheetIndex), 0);
        createHead(sheet);
        Object value;
        Label label;
        do {

            for (Object data : dataList) {
                if (sheetIndex < countPage && ((rowIndex - 1) % maxEntityInOnePage) == 0 && rowIndex > 1) {
                    roeIndexPage = 1;
                    sheetIndex++;
                    sheet = workBook.createSheet(createSheetName(sheetIndex), 0);
                    createHead(sheet);// 创建头部
                }
                int count = 0;
                if (isUseIndex()) {
                    label = new Label(0, rowIndex, "" + rowIndex);
                    sheet.setColumnView(0, 3);
                    sheet.addCell(label);
                    count++;
                }
                for (int i = 0 + count; i < fields.size() + count; i++) {
                    value = getValue(data, fields.get(i - count).getField());
                    if (value != null) {
                        label = new Label(i, roeIndexPage, value.toString());
                        if (value instanceof Date) {
                            String datePattern = fields.get(i - count).getDatePattern();
                            if (datePattern != null) {
                                SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
                                label = new Label(i, roeIndexPage, sdf.format(value));
                            }
                        }
                        sheet.setColumnView(i, fields.get(i - count).getColumnWidth());
                        sheet.addCell(label);
                    }
                }
                roeIndexPage++;
                rowIndex++;
            }
        } while (rowIndex <= dataList.size());
        workBook.write();
        workBook.close();
        os.flush();
    }

    private void exportExcel07() throws IOException, WriteException {
        Collection<?> dataList;
        WritableWorkbook workBook = Workbook.createWorkbook(os);
        int sheetIndex = 1;
        WritableSheet sheet = workBook.createSheet(createSheetName(sheetIndex), 0);
        int rowIndex = 1;
        createHead(sheet);// 创建头部
        Object value;
        do {
            dataList = dataSource.getData();

            for (Object data : dataList) {
                int count = 0;
                if (isUseIndex()) {
                    Label label = new Label(0, rowIndex, "" + rowIndex);
                    sheet.setColumnView(0, 3);
                    sheet.addCell(label);
                    count++;
                }
                for (int i = 0 + count; i < fields.size() + count; i++) {
                    value = getValue(data, fields.get(i - count).getField());
                    if (value != null) {
                        WritableCell label = new Label(i, rowIndex, value.toString());
                        if (value instanceof Date) {
                            String datePattern = fields.get(i - count).getDatePattern();
                            if (datePattern != null) {
                                SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
                                label = new Label(i, rowIndex, sdf.format(value));
                            }
                        } else if (fields.get(i - count).isNumber()) {
                            label = new Number(i, rowIndex, Double.parseDouble(value.toString()));
                        }
                        sheet.setColumnView(i, fields.get(i - count).getColumnWidth());
                        sheet.addCell(label);
                    }
                }
                rowIndex++;
            }
        } while (rowIndex <= dataList.size());
        workBook.write();
        workBook.close();
        os.flush();
    }

    /**
     * 将指定行创建为表头
     *
     * @param sheet
     * @throws WriteException
     * @throws RowsExceededException
     */
    private void createHead(WritableSheet sheet) throws WriteException {
        DataField field;
        int count = 0;
        Label label;
        if (isUseIndex()) {
            label = new Label(0, 0, "序号"); // 第一行第一列为序号
            sheet.setColumnView(0, 3); // 第一列宽度为3
            sheet.addCell(label); // 把定义好的单元格添加到工作表中
            count++;
        }
        for (int i = 0 + count; i < fields.size() + count; i++) {
            field = fields.get(i - count);
            WritableFont font = new WritableFont(WritableFont.createFont("宋体"), 10, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.WHITE);// 字体样式
            WritableCellFormat wcf = new WritableCellFormat(font);
            wcf.setBackground(Colour.BLUE_GREY);// 背景色
            label = new Label(i, 0, field.getName(), wcf);
            sheet.setColumnView(i, field.getColumnWidth());
            sheet.addCell(label);
            continue;
        }
    }

    private String createSheetName(int index) {
        if (sheetName == null) {
            this.sheetName = "sheet";
        }
        return this.sheetName + index;
    }

    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }
}
